#!/usr/bin/env python3
"""
用户服务测试运行器
================

运行所有用户服务的测试，包括单元测试和集成测试
"""

import os
import sys
import asyncio
import subprocess
import argparse
from pathlib import Path
from typing import List, Dict, Any

# 添加服务根目录到Python路径
service_root = Path(__file__).parent.parent
sys.path.insert(0, str(service_root))
sys.path.insert(0, str(service_root.parent.parent.parent))  # 项目根目录

def run_command(command: List[str], cwd: str = None) -> Dict[str, Any]:
    """运行命令并返回结果"""
    try:
        result = subprocess.run(
            command,
            cwd=cwd,
            capture_output=True,
            text=True,
            timeout=300  # 5分钟超时
        )
        
        return {
            "success": result.returncode == 0,
            "returncode": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr
        }
    except subprocess.TimeoutExpired:
        return {
            "success": False,
            "returncode": -1,
            "stdout": "",
            "stderr": "命令执行超时"
        }
    except Exception as e:
        return {
            "success": False,
            "returncode": -1,
            "stdout": "",
            "stderr": str(e)
        }


def setup_test_environment():
    """设置测试环境"""
    print("🔧 设置测试环境...")
    
    # 设置环境变量
    os.environ["ENVIRONMENT"] = "testing"
    os.environ["TESTING"] = "true"
    os.environ["DEBUG"] = "false"
    
    # 设置测试数据库配置
    os.environ["REDFIRE_MYSQL_HOST"] = "localhost"
    os.environ["REDFIRE_MYSQL_PORT"] = "3307"
    os.environ["REDFIRE_MYSQL_USERNAME"] = "redfire_test"
    os.environ["REDFIRE_MYSQL_PASSWORD"] = "redfire_test_2025"
    os.environ["REDFIRE_MYSQL_DATABASE"] = "redfire_test"
    
    print("✅ 测试环境设置完成")


def run_linting():
    """运行代码检查"""
    print("\n🔍 运行代码检查...")
    
    service_dir = str(service_root)
    
    # 运行flake8
    flake8_result = run_command([
        "python", "-m", "flake8", 
        ".", 
        "--config", "setup.cfg",
        "--exclude", "__pycache__,*.pyc,.git,venv"
    ], cwd=service_dir)
    
    if flake8_result["success"]:
        print("✅ Flake8 检查通过")
    else:
        print(f"❌ Flake8 检查失败:")
        print(flake8_result["stderr"])
    
    # 运行mypy（如果可用）
    mypy_result = run_command([
        "python", "-m", "mypy",
        ".",
        "--ignore-missing-imports",
        "--follow-imports", "silent"
    ], cwd=service_dir)
    
    if mypy_result["success"]:
        print("✅ MyPy 类型检查通过")
    else:
        print(f"⚠️ MyPy 类型检查警告:")
        print(mypy_result["stderr"][:500] + "..." if len(mypy_result["stderr"]) > 500 else mypy_result["stderr"])
    
    return flake8_result["success"]


def run_unit_tests(verbose: bool = False, coverage: bool = True):
    """运行单元测试"""
    print("\n🧪 运行单元测试...")
    
    service_dir = str(service_root)
    
    # 构建pytest命令
    command = [
        "python", "-m", "pytest",
        "tests/unit/",
        "-v" if verbose else "-q",
        "--tb=short",
        "--strict-markers",
        "-m", "not slow"  # 排除慢速测试
    ]
    
    if coverage:
        command.extend([
            "--cov=.",
            "--cov-report=term-missing",
            "--cov-report=html:htmlcov/unit"
        ])
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print("✅ 单元测试通过")
    else:
        print("❌ 单元测试失败:")
        print(result["stdout"])
        print(result["stderr"])
    
    return result["success"]


def run_integration_tests(verbose: bool = False):
    """运行集成测试"""
    print("\n🔗 运行集成测试...")
    
    service_dir = str(service_root)
    
    command = [
        "python", "-m", "pytest",
        "tests/integration/",
        "-v" if verbose else "-q",
        "--tb=short",
        "--strict-markers",
        "-m", "integration and not slow"
    ]
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print("✅ 集成测试通过")
    else:
        print("❌ 集成测试失败:")
        print(result["stdout"])
        print(result["stderr"])
    
    return result["success"]


def run_slow_tests(verbose: bool = False):
    """运行慢速测试"""
    print("\n🐌 运行慢速测试...")
    
    service_dir = str(service_root)
    
    command = [
        "python", "-m", "pytest",
        "tests/",
        "-v" if verbose else "-q",
        "--tb=short",
        "--strict-markers",
        "-m", "slow"
    ]
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print("✅ 慢速测试通过")
    else:
        print("❌ 慢速测试失败:")
        print(result["stdout"])
        print(result["stderr"])
    
    return result["success"]


def run_specific_test_file(test_file: str, verbose: bool = False):
    """运行特定测试文件"""
    print(f"\n🎯 运行测试文件: {test_file}")
    
    service_dir = str(service_root)
    
    command = [
        "python", "-m", "pytest",
        test_file,
        "-v" if verbose else "-q",
        "--tb=short"
    ]
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print(f"✅ 测试文件 {test_file} 通过")
    else:
        print(f"❌ 测试文件 {test_file} 失败:")
        print(result["stdout"])
        print(result["stderr"])
    
    return result["success"]


def generate_test_report():
    """生成测试报告"""
    print("\n📊 生成测试报告...")
    
    service_dir = str(service_root)
    
    # 生成HTML报告
    command = [
        "python", "-m", "pytest",
        "tests/",
        "--html=reports/test_report.html",
        "--self-contained-html",
        "--tb=short",
        "-q"
    ]
    
    # 确保报告目录存在
    reports_dir = service_root / "reports"
    reports_dir.mkdir(exist_ok=True)
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print("✅ 测试报告生成成功")
        print(f"📄 报告位置: {reports_dir / 'test_report.html'}")
    else:
        print("❌ 测试报告生成失败")
    
    return result["success"]


def check_test_coverage():
    """检查测试覆盖率"""
    print("\n📈 检查测试覆盖率...")
    
    service_dir = str(service_root)
    
    # 运行覆盖率测试
    command = [
        "python", "-m", "pytest",
        "tests/",
        "--cov=.",
        "--cov-report=term-missing",
        "--cov-report=html:htmlcov",
        "--cov-report=xml",
        "--cov-fail-under=70",  # 要求至少70%覆盖率
        "-q"
    ]
    
    result = run_command(command, cwd=service_dir)
    
    if result["success"]:
        print("✅ 测试覆盖率达标")
    else:
        print("❌ 测试覆盖率不足")
        print(result["stdout"])
    
    return result["success"]


def main():
    """主函数"""
    parser = argparse.ArgumentParser(description="用户服务测试运行器")
    parser.add_argument("--type", choices=["all", "unit", "integration", "slow", "lint"], 
                       default="all", help="要运行的测试类型")
    parser.add_argument("--file", help="运行特定测试文件")
    parser.add_argument("--verbose", "-v", action="store_true", help="详细输出")
    parser.add_argument("--no-coverage", action="store_true", help="不生成覆盖率报告")
    parser.add_argument("--no-lint", action="store_true", help="跳过代码检查")
    parser.add_argument("--report", action="store_true", help="生成HTML测试报告")
    
    args = parser.parse_args()
    
    # 设置测试环境
    setup_test_environment()
    
    success_count = 0
    total_count = 0
    
    # 运行特定测试文件
    if args.file:
        total_count = 1
        if run_specific_test_file(args.file, args.verbose):
            success_count += 1
    else:
        # 代码检查
        if not args.no_lint and args.type in ["all", "lint"]:
            total_count += 1
            if run_linting():
                success_count += 1
        
        # 单元测试
        if args.type in ["all", "unit"]:
            total_count += 1
            if run_unit_tests(args.verbose, not args.no_coverage):
                success_count += 1
        
        # 集成测试
        if args.type in ["all", "integration"]:
            total_count += 1
            if run_integration_tests(args.verbose):
                success_count += 1
        
        # 慢速测试
        if args.type in ["all", "slow"]:
            total_count += 1
            if run_slow_tests(args.verbose):
                success_count += 1
    
    # 生成报告
    if args.report:
        generate_test_report()
    
    # 检查覆盖率
    if not args.no_coverage and args.type == "all":
        total_count += 1
        if check_test_coverage():
            success_count += 1
    
    # 输出总结
    print(f"\n📋 测试总结:")
    print(f"✅ 成功: {success_count}/{total_count}")
    print(f"❌ 失败: {total_count - success_count}/{total_count}")
    
    if success_count == total_count:
        print("🎉 所有测试都通过了!")
        sys.exit(0)
    else:
        print("💥 部分测试失败，请检查错误信息")
        sys.exit(1)


if __name__ == "__main__":
    main()
